﻿Imports Framework

Namespace Backup
    Public Class Jobs

#Region " Events "
        Public Shared Event Updated(ByVal job As Entities.Backup.Job)
        Public Shared Event UpdatedGUI(ByVal job As Entities.Backup.Job)
        Friend Shared Sub OnUpdated(ByVal job As Entities.Backup.Job)
            RaiseEvent Updated(job)
            Framework.Threading.Invoke(AddressOf OnUpdated_Callback, job)
        End Sub
        Private Shared Sub OnUpdated_Callback(ByVal job As Entities.Backup.Job)
            RaiseEvent UpdatedGUI(job)
        End Sub
        Public Shared Event Deleted(ByVal job As Entities.Backup.Job)
        Public Shared Event DeletedGUI(ByVal job As Entities.Backup.Job)
        Friend Shared Sub OnDeleted(ByVal job As Entities.Backup.Job)
            RaiseEvent Deleted(job)
            Framework.Threading.Invoke(AddressOf OnDeleted_Callback, job)
        End Sub
        Private Shared Sub OnDeleted_Callback(ByVal job As Entities.Backup.Job)
            RaiseEvent DeletedGUI(job)
        End Sub
#End Region
        Shared Sub New()
            Try
                mCache = DataStore.Backup.Jobs.GetAll
            Catch ex As Exception
                Framework.Misc.HandleException(ex)
            End Try
        End Sub
        Private Shared mCache As New Generic.List(Of Entities.Backup.Job)

        Public Shared Function GetAll() As Generic.List(Of Entities.Backup.Job)
            Return mCache.ToList ' DataStore.Backup.Jobs.GetAll
        End Function
        Public Shared Sub Save(ByVal job As Entities.Backup.Job)
            DataStore.Backup.Jobs.Save(job)
            If Not mCache.Contains(job) Then mCache.Add(job)
            OnUpdated(job)
        End Sub

        Public Shared Function CreateNew() As Entities.Backup.Job
            Dim clsRet As New Entities.Backup.Job
            clsRet.Enabled = True
            clsRet.Status = Entities.Backup.JobStatus.Idle
            clsRet.UniqueId = Framework.Misc.GenerateUniqueId
            clsRet.Inertia = New Entities.Backup.Inertia
            clsRet.Inertia.OverridenNextRun = True
            clsRet.Source = New Entities.Backup.Source
            clsRet.Source.Filter = New Entities.Backup.FileFilter
            clsRet.Actions = New Entities.Backup.Actions
            clsRet.Actions.OnCompletion = New Entities.Backup.CompletionAction
            clsRet.Actions.OnCompletion.SendEmail = True
            clsRet.Actions.OnCompletion.ShowTrayNotification = True
            clsRet.Actions.OnFail = New Entities.Backup.FailAction
            clsRet.Actions.OnFail.SendEmail = True
            clsRet.Actions.OnFail.ShowTrayNotification = True
            clsRet.Actions.OnError = New Entities.Backup.ErrorAction
            clsRet.Actions.OnError.SendEmail = True
            clsRet.Actions.OnError.ShowTrayNotification = True
            clsRet.Actions.OnError.RetryBeforeFailing = True
            clsRet.Actions.OnError.RetryCount = 5
            clsRet.Actions.OnError.RetryDelayInSeconds = 5 * 60
            Return clsRet
        End Function

        Public Shared Function Copy(ByVal job As Entities.Backup.Job) As Entities.Backup.Job
            Dim clsRet As Entities.Backup.Job
            clsRet = Framework.Serialization.FromXml(Of Entities.Backup.Job)(Framework.Serialization.ToXml(job))
            clsRet.Id = 0
            clsRet.UniqueId = Framework.Misc.GenerateUniqueId
            clsRet.Status = Entities.Backup.JobStatus.Idle
            Return clsRet
        End Function
        Public Shared Sub Delete(ByVal jobs As Generic.List(Of Entities.Backup.Job))
            Using t As New Framework.Data.TransactionScope
                For Each clsJob As Entities.Backup.Job In jobs
                    DataStore.Backup.Jobs.Delete(clsJob, t)
                Next
                t.Complete()
            End Using
            For Each clsJob As Entities.Backup.Job In jobs
                OnDeleted(clsJob)
            Next
        End Sub
        Public Shared Sub SetNewStatus(ByVal job As Entities.Backup.Job, ByVal newStatus As Entities.Backup.JobStatus)
            If job.Status <> newStatus Then
                job.Status = newStatus
                OnUpdated(job)
            End If
        End Sub

        Public Shared Function CalculateNextRunTime(ByVal schedule As Entities.Backup.SchduleBase) As Date
            Return CalculateNextRunTime(schedule, Now.ToUniversalTime)
        End Function
        Public Shared Function CalculateNextRunTime(ByVal schedule As Entities.Backup.SchduleBase, ByVal after As Date) As Date
            after = after.ToLocalTime
            If TypeOf schedule Is Entities.Backup.RunOnChangeSchedule Then
                Return DateTime.MinValue
            ElseIf TypeOf schedule Is Entities.Backup.HourlySchedule Then
                Dim clsS As Entities.Backup.HourlySchedule = CType(schedule, Entities.Backup.HourlySchedule)
                Dim dtNow As Date = after
                Dim dtCurrentHour As Date = dtNow.Date.AddHours(dtNow.Hour)
                Dim dtRet As Date = dtCurrentHour.Add(clsS.Offset)
                While dtRet < after
                    dtRet = dtRet.AddHours(1)
                End While
                Return dtRet.ToUniversalTime
            ElseIf TypeOf schedule Is Entities.Backup.DailySchedule Then
                Dim clsS As Entities.Backup.DailySchedule = CType(schedule, Entities.Backup.DailySchedule)
                Dim dtCurrentDay As Date = after.Date
                Dim dtRet As Date = dtCurrentDay.Add(clsS.Offset)
                While dtRet < after
                    dtRet = dtRet.AddDays(1)
                End While
                Return dtRet.ToUniversalTime
            ElseIf TypeOf schedule Is Entities.Backup.WeeklySchedule Then
                Dim clsS As Entities.Backup.WeeklySchedule = CType(schedule, Entities.Backup.WeeklySchedule)
                Dim blnValid As Boolean = False
                For i As Integer = 0 To clsS.DaysToRunOn.Count - 1
                    If clsS.DaysToRunOn(i) Then
                        blnValid = True
                    End If
                Next
                If Not blnValid Then
                    Return DateTime.MaxValue
                Else
                    Dim dtWeekStart As Date = after.Date
                    If dtWeekStart.DayOfWeek <> DayOfWeek.Monday Then dtWeekStart = dtWeekStart.AddDays(-(CInt(dtWeekStart.DayOfWeek) - 1))
                    Dim dtRet As Date = dtWeekStart.Add(clsS.Offset)
                    While dtRet < after Or Not clsS.DaysToRunOn(dtRet.DayOfWeekIso)
                        dtRet = dtRet.AddDays(1)
                    End While
                    Return dtRet.ToUniversalTime
                End If
            ElseIf TypeOf schedule Is Entities.Backup.MonthlySchedule Then
                Dim clsS As Entities.Backup.MonthlySchedule = CType(schedule, Entities.Backup.MonthlySchedule)
                Dim blnValid As Boolean = False
                For i As Integer = 0 To clsS.DaysToRunOn.Count - 1
                    If clsS.DaysToRunOn(i) Then
                        blnValid = True
                    End If
                Next
                If Not blnValid Then
                    Return DateTime.MaxValue
                Else
                    Dim dtMonthStart As Date = after.Date
                    If dtMonthStart.Day <> 1 Then dtMonthStart = dtMonthStart.AddDays(-(dtMonthStart.Day - 1))
                    Dim dtRet As Date = dtMonthStart.Add(clsS.Offset)
                    While dtRet < after Or Not clsS.DaysToRunOn(dtRet.DayOfWeekIso)
                        dtRet = dtRet.AddDays(1)
                    End While
                    Return dtRet.ToUniversalTime
                End If
            Else
                Throw New NotImplementedException
            End If
        End Function
    End Class
End Namespace